package com.example.design.clean_craftsmanship

/**
 *非官方示例
 **/
class Bowling {
    private val mScoreList = mutableListOf<RoundScore>()
    private var mIsStrike = false
    private var mIsSpare = false
    private var mIsFirstRoll = true
    var firstRoll = 0
    var secondRoll = 0

    fun testRoll(int: Int): Int {
        return int.apply {
            if (mIsFirstRoll) {
                firstRoll = this
                if (mScoreList.size != 10)
                    mScoreList.add(RoundScore(this))

                //如果是全中或補中
                if (mIsStrike) {
                    mScoreList[mScoreList.size - 2].secondScore = this
                    if (mScoreList.size - 3 >= 0) {
                        if (mScoreList[mScoreList.size - 3].firstScore == 10) {
                            mScoreList[mScoreList.size - 3].thirdScore = this
                        }
                    }
                } else if (mIsSpare) {
                    mScoreList[mScoreList.size - 2].thirdScore = this
                }

                if (this == 10) {
                    mIsStrike = true
                    mIsFirstRoll = true
                } else {
                    mIsFirstRoll = false
                }

            } else {
                secondRoll = this
                mIsFirstRoll = true
                mIsSpare = firstRoll + this == 10
                if (mIsStrike) {
                    mScoreList[mScoreList.size - 2].thirdScore = this
                    mIsStrike = false
                }
                if (mScoreList.size != 10)
                    mScoreList.last().secondScore = this

            }
        }
    }

    fun allRoll() {
        for (i in 1..10) {
            oneRoll()
            if (!mIsFirstRoll) oneRoll()
            if (getScore(10) == 10) {
                testRoll(10)
                testRoll(10)
            }
        }
    }

    fun perfectGame() {
        for (i in 1..10) {
            testRoll(10)
            if (getScore(10) == 10) {
                testRoll(10)
                testRoll(10)
            }
        }
    }

    fun oneRoll(): Int {
        return (if (mIsFirstRoll) (0..10) else (0..10 - firstRoll))
            .random().apply {
                if (mIsFirstRoll) {
                    firstRoll = this
                    if (mScoreList.size != 10)
                        mScoreList.add(RoundScore(this))

                    //如果是全中或補中
                    if (mIsStrike) {
                        mScoreList[mScoreList.size - 2].secondScore = this
                        if (mScoreList.size - 3 >= 0) {
                            if (mScoreList[mScoreList.size - 3].firstScore == 10) {
                                mScoreList[mScoreList.size - 3].thirdScore = this
                            }
                        }
                    } else if (mIsSpare) {
                        mScoreList[mScoreList.size - 2].thirdScore = this
                    }

                    if (this == 10) {
                        mIsStrike = true
                        mIsFirstRoll = true
                    } else {
                        mIsFirstRoll = false
                    }

                } else {
                    secondRoll = this
                    mIsFirstRoll = true
                    mIsSpare = firstRoll + this == 10
                    if (mIsStrike) {
                        mScoreList[mScoreList.size - 2].thirdScore = this
                        mIsStrike = false
                    }
                    if (mScoreList.size != 10)
                        mScoreList.last().secondScore = this

                }
            }
    }

    fun getScore(): Int {
        var score = 0
        mScoreList.forEach {
            println(it.toString())
            score += negativeNumber(it.thirdScore) + it.firstScore + negativeNumber(it.secondScore)
        }
        return score
    }


    fun getScore(round: Int): Int {
        if (mScoreList.size < round) return -1
        val roundScore = mScoreList[round - 1]
//        println(roundScore.toString())
        return roundScore.firstScore + negativeNumber(roundScore.secondScore) + negativeNumber(
            roundScore.thirdScore
        )
    }

    fun reset() {
        mScoreList.clear()
    }
//    fun isStrike(): Boolean {
//        return mIsStrike
//    }
//
//    fun isSpare(): Boolean {
//        return mIsSpare
//    }

    private fun negativeNumber(int: Int) = if (int < 0) 0 else int

}

data class RoundScore(val firstScore: Int, var secondScore: Int = -1, var thirdScore: Int = -1)